<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <link href="https://cdn.bootcdn.net/ajax/libs/animate.css/2.0/animate.min.css" rel="stylesheet">
  <title>Document</title>
  <style>

    /* 入场之前 */
    .fade-enter, .fade-leave-to{
      opacity:0;
    }
    /* 过渡定义 */
    .fade-enter-active, .fade-leave-active{
      transition:opacity 1s;
    }

  </style>
</head>
<body>
  <div id="app">
    <!-- 弹窗组件  @update:show=""-->
    <message :show.sync="show" ref="msgSuccess">
      <template v-slot:val='val'>
        {{val.val}}
      </template>
      <template v-slot:title>
        <strong>恭喜</strong>
      </template>
      <!-- 默认插槽 -->
      <template>
        新增成功
      </template>
    </message>
    <!-- 新增课程组件 -->
    <course-add v-model="course" @add-course='addCourse'></course-add>
    <!-- 列表组件 -->
    <course-list :courses="courses"></course-list>
    
    <p>总和:{{count}}</p>
    <p>总和:{{totalCount}}</p>
    <div>
      <button @click="$bus.$emit('message-close')">清空提示框</button>
    </div>
  </div>

  <script src="vue.js"></script>
  <script>
    // 总线
    Vue.prototype.$bus = new Vue()
    // 弹窗组件
    Vue.component('message', {
      data(){
        return {
          title:'hello',
          // show: false
        }
      },
      props: ['show'],
      template: `
      <transition 
        enter-active-class="animated bounceIn" 
        leave-active-class="animated bounceOut">
        <div class="message-box" v-if="show">
          <slot name="title" ></slot>
          <slot></slot>
          <slot name="val" :val='title'></slot>
          <span class='message-close' @click="$emit('update:show', false)">X</span>
        </div>
      </transition>
      `,
      mounted(){
        this.$bus.$on('message-close', ()=>{
          this.$emit('update:show', false)
        })
      },
      methods:{
        toggle(){
          // this.show = !this.show
        }
      }
    })
    // 课程新增组件
    Vue.component('course-add', {
      props: ['value'],
      template: `
      <p>
        <input type="text" :value="value" @input="onInput" ref="inp" name="" id=""><button @click="submit">提交</button>
      </p>
      `,
      methods:{
        submit(){
          // 派发事件通知组件新增
          this.$emit('add-course')
        },
        onInput(e){
          this.$emit('input',e.target.value)
        }
      },
      mounted(){
        this.$refs.inp.focus()
      }
    })
    // 列表组件
    Vue.component('course-list',{
      data(){
        return {
          selectCourse: ''
        }
      },
      props: {
        courses: {
          type:Array,
          default: []
        }
      },
      template: `
      <ul>
        <li v-for="c in courses" :key='c'>{{c}}</li>
      </ul>
      `
    })

    function getCourses(){
      return new Promise(resolve=>{
        setTimeout(()=>{
          resolve(['Python', 'Java', 'JavaScript'])
        }, 500)
      })
    }

    const app = new Vue({
      el: '#app',
      data(){
        return {
          course:'',
          courses: [],
          totalCount: 0,
          show:false
        }
      },
      async created(){
        // 组件实例已创建，未挂载，dom元素不存在
        const courses = await getCourses()
        this.courses = courses
      },
      // $el 就是渲染出来的dom元素
      mounted(){},
      methods:{
        addCourse(){
          this.courses.push(this.course)
          this.course = ''
          this.show = true
          this.$refs.msgSuccess.toggle()
        },
        beforeEnter(el){
          // 动画开始状态
          el.style.opacity = 0
        },
        enter(el, done){
          // 触发浏览器回流
          document.body.offsetHeight
          // 动画结束状态
          el.style.opacity = 1
          // 监听动画结束事件，执行done函数
          el.addEventListener('transitionend', done)
        },
        beforeLeave(el){
          el.style.opacity = 1
        },
        leave(el, done){
          document.body.offsetHeight
          el.style.opacity = 0
          el.addEventListener('transitionend', done)
        }
      },
      // 计算属性 一个值是由其他值得来的 多个值影响一个值
      computed: {
        // 缓存性，如果没有发生变化，页面不会重新渲染
        count(){
          return this.courses.length + '门'
        }
      },
      // 一个值变化，做一些事情，一个值影响多个值
      // watch: {
      //   courses(newVal, oldVal){
      //     this.totalCount = newVal.length + '课'
      //   }
      // },
      watch: {
        courses: {
          immediate:true,
          // deep: true,
          handler(newVal, oldVal){
            this.totalCount = newVal.length + '课'
          }
        }
      },


    })

    // 虚拟DOM渲染函数 模板转换成js函数 
    console.log(app.$options.render)

    

  </script>
</body>
</html>